Update index this time...
[clinton/website/site/unknownlamer.org.git] / Metaobject Protocols.html
CommitLineData
2aff8b5c 1<?xml version="1.0" encoding="utf-8" ?>
2<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
3 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
4<html xmlns="http://www.w3.org/1999/xhtml">
5 <head>
6 <title>Metaobject Protocols</title>
7 <meta name="generator" content="muse.el" />
8 <meta http-equiv="Content-Type"
9 content="text/html; charset=utf-8" />
10<link rel="stylesheet" href="default.css" media="screen" />
11 </head>
12 <body>
13 <h1>Metaobject Protocols</h1>
14 <div class="contents">
15<dl>
16<dt>
17<a href="#sec1">Background</a>
18</dt>
19<dd>
20<dl>
21<dt>
22<a href="#sec2">Object Protocols</a>
23</dt>
24<dt>
25<a href="#sec3">CLOS Way of OO</a>
26</dt>
27<dd>
28<dl>
29<dt>
30<a href="#sec4">Classes for scratch data and types</a>
31</dt>
32<dt>
33<a href="#sec5">Generics with methods that implement protocols</a>
34</dt>
35</dl>
36</dd>
37</dl>
38</dd>
39<dt>
40<a href="#sec6">Limitations of Default Language Behavior</a>
41</dt>
42<dd>
43<dl>
44<dt>
45<a href="#sec7">Slot Storage</a>
46</dt>
47<dt>
48<a href="#sec8">Design Patterns</a>
49</dt>
50</dl>
51</dd>
52<dt>
53<a href="#sec9">Metasoftware</a>
54</dt>
55<dd>
56<dl>
57<dt>
58<a href="#sec10">Runtime Generated Classes</a>
59</dt>
60<dt>
61<a href="#sec11">Object Inspection</a>
62</dt>
63</dl>
64</dd>
65<dt>
66<a href="#sec12">Metaobject Protocols</a>
67</dt>
68<dd>
69<dl>
70<dt>
71<a href="#sec13">Limited/Generalized Internals of the Implementation</a>
72</dt>
73<dt>
74<a href="#sec14">Classes of MOPs</a>
75</dt>
76<dd>
77<dl>
78<dt>
79<a href="#sec15">Reflective</a>
80</dt>
81<dt>
82<a href="#sec16">Intercessory</a>
83</dt>
84</dl>
85</dd>
86<dt>
87<a href="#sec17">Violation of Encapsulation?</a>
88</dt>
89</dl>
90</dd>
91<dt>
92<a href="#sec18">MOP Design Principles</a>
93</dt>
94<dd>
95<dl>
96<dt>
97<a href="#sec19">Layered Protocol</a>
98</dt>
99<dd>
100<dl>
101<dt>
102<a href="#sec20">Top level <strong>must</strong> call lower level functions</a>
103</dt>
104<dt>
105<a href="#sec21">Lower level methods are easier to customize</a>
106</dt>
107</dl>
108</dd>
109<dt>
110<a href="#sec22">Functional Where Possible</a>
111</dt>
112<dd>
113<dl>
114<dt>
115<a href="#sec23">Memoization</a>
116</dt>
117<dt>
118<a href="#sec24">Cleaner Code</a>
119</dt>
120</dl>
121</dd>
122<dt>
123<a href="#sec25">Procedural Only Where Neccesary</a>
124</dt>
125</dl>
126</dd>
127<dt>
128<a href="#sec26">Examples</a>
129</dt>
130<dd>
131<dl>
132<dt>
133<a href="#sec27">Object Inspector</a>
134</dt>
135<dt>
136<a href="#sec28">Observer Design Pattern</a>
137</dt>
138<dt>
139<a href="#sec29">Real World</a>
140</dt>
141<dd>
142<dl>
143<dt>
144<a href="#sec30">UCW and Arnesi</a>
145</dt>
146<dt>
147<a href="#sec31">CLSQL</a>
148</dt>
149<dt>
150<a href="#sec32">Elephant</a>
151</dt>
152</dl>
153</dd>
154</dl>
155</dd>
156<dt>
157<a href="#sec33">Sources &amp;amp; Further Reading</a>
158</dt>
159<dd>
160<dl>
161<dt>
162<a href="#sec34">Sources</a>
163</dt>
164<dd>
165<dl>
166<dt>
167<a href="#sec35">The Art of the Metaobject Protocol</a>
168</dt>
169<dt>
170<a href="#sec36">CLOS MOP Specification</a>
171</dt>
172<dt>
173<a href="#sec37">Metaobject Protocols: Why We Want Them and What Else They Can Do</a>
174</dt>
175<dt>
176<a href="#sec38">Why Are Black Boxes so Hard to Reuse?</a>
177</dt>
178</dl>
179</dd>
180<dt>
181<a href="#sec39">Further Reading</a>
182</dt>
183<dd>
184<dl>
185<dt>
186<a href="#sec40">A Metaobject Protocol for C++</a>
187</dt>
188<dt>
189<a href="#sec41">Open Implementations and Metaobject Protocols</a>
190</dt>
191</dl>
192</dd>
193</dl>
194</dd>
195</dl>
196</div>
197
198
199<!-- Page published by Emacs Muse begins here --><p>In Fall of 2006 I did a small project on Metaobject Protocols for my
200CS 331 class. Here lie my notes which may perhaps be useful to
201others. I hope to expand them into something more useful over time.</p>
202
203<h2><a name="sec1" id="sec1"></a>
204Background</h2>
205
206<h3><a name="sec2" id="sec2"></a>
207Object Protocols</h3>
208
209<p class="first">An object protocol is a set of methods and specification of the
210interactions between the methods which provide some generic behavior
211(e.g. of a sequence) that are then implemented by classes which
212conform to the protocol (e.g. a vector or list). In most object
213systems a class contains both the methods which implement a protocol
214and the data used by the implementation. The intent is to emulate
215state machines which pass messages between each other.</p>
216
217
218<h3><a name="sec3" id="sec3"></a>
219CLOS Way of OO</h3>
220
221<p class="first">The Common Lisp Object System (CLOS) is different. It separates
222the data and method concepts into classes and generics. A class
223contains data fields only, and a generic has methods specialized for
224certain types attached to it. This seems a bit weird at first, but is
225significantly more powerful as it encourages complete encapsulation
226through its use of classes primarily for method specialization rather
227than for state storage.</p>
228
229
230<h4><a name="sec4" id="sec4"></a>
231Classes for scratch data and types</h4>
232
233<p class="first">In CLOS classes store data in slots (which are the same as data
234members). Encapsulation is not provided; any bit of code can use
235<code>slot-value</code> to access or set the value of a slot. This may seem odd at
236first, but encapsulation is of questionable importance as the slots
237are meant only to be used by the protocol defined around the class.</p>
238
239<p>Classes are defined with defclass</p>
240
241<pre class="src">
242(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">name</span> (superclasses ...)
243 ((slot-name <span style="color: #b0c4de;">:accessor</span> slot-accessor ...)
244 ...)
245 (class-options ...))
246
247(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">example</span> ()
248 ((foo <span style="color: #b0c4de;">:accessor</span> foo-of <span style="color: #b0c4de;">:initform</span> 5)))
249
250(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">example-child</span> (example)
251 ((bar <span style="color: #b0c4de;">:accessor</span> bar-of <span style="color: #b0c4de;">:initform</span> (list 1 2 3))))
252</pre>
253
254<p>Slot defintions have several option; the above example shows only the
255<code>:accessor</code> and <code>:initform</code> options which are the most commonly
256used. <code>:accessor</code> generates an accessor for the slot (e.g. if you have
257an instance of <code>example</code> you can <code>(setf (foo-of some-example-instance) 'some-value)</code> to set and <code>(foo-of some-example-instance)</code> to access the
258value). <code>:initform</code> provides a default initial value for the slot as a
259symbolic expression to be evaluated when an instance is created.</p>
260
261
262<h4><a name="sec5" id="sec5"></a>
263Generics with methods that implement protocols</h4>
264
265<p class="first">Generics are like normal functions in Lisp, but they only provide a
266lambda list (parameter list). Methods are added to the generic which
267specialize on the types of their parameters, and provide the actual
268implementation. This allows for rich layered protocols to be developed
269which can enable selective modification of individual facets with
270minimal code.</p>
271
272<pre class="src">
273(<span style="color: #00ffff;">defgeneric</span> <span style="color: #87cefa;">generic</span> (parameters ...)
274 (options) ...)
275
276(<span style="color: #00ffff;">defmethod</span> <span style="color: #87cefa;">generic-name</span> ((parameter type) parameter ...)
277 <span style="color: #b3b3b3;">"documentation string"</span>
278 body)
279
280(<span style="color: #00ffff;">defgeneric</span> <span style="color: #87cefa;">foo</span> (bar baz quux)
281 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Process the baz with the quux capacitor to make the
282foo widget fly into the sky at warp speed"</span>))
283
284(<span style="color: #00ffff;">defmethod</span> <span style="color: #87cefa;">foo</span> ((bar example) baz (quux capacitor))
285 (launch bar (process-with quux baz)))
286</pre>
287
288<p>A method lambda list differs from a normal lambda list only in that it
289can specify the type of the parameter using the notation <code>(name type)</code>.
290Note also that methods can specialize on the types of every
291argument and not just the first one. This is quite powerful for
292reasons outside of the scope of this presentation.</p>
293
294
295
296
297<h2><a name="sec6" id="sec6"></a>
298Limitations of Default Language Behavior</h2>
299
300<p class="first">The behavior of a language is a compromise between many competing
301issues that attempts to be as generally useful as possible, and most
302applications will have no issue with the default behavior. There are,
303however, certain applications that could be cleanly written with minor
304modifications to the behavior of the language, but would be impossible
305or quite difficult to write otherwise.</p>
306
307<h3><a name="sec7" id="sec7"></a>
308Slot Storage</h3>
309
310<p class="first">Most languages choose to preallocate storage for all of the slots of
311an instance. Imagine a contact database that stored information about
312people as slots of the class. There may be dozens of slots, but often
313many of them will be left blank. If slot storage is preallocated much
314memory will be wasted and the system may not be able to fit into the
315memory of the hardware it must run on (perhaps for financial reasons,
316huge datasets, etc.).</p>
317
318<p>To save memory the author of the contact database must implement his
319own system to store properties and allocate them lazily. This
320represents a fair bit of effort, and would implement a system that
321differed from the existing slot system of classes only in the method
322of data storage.</p>
323
324<p>It would be useful if there were a way to customize instance
325allocation. The customizations would be minor and require overriding
326only the initial allocation behavior and the behavior of the first
327assignment to the slot. It is a a trivial problem in a language that
328allows customization of these.</p>
329
330
331<h3><a name="sec8" id="sec8"></a>
332Design Patterns</h3>
333
334<p class="first">Design Patterns are generalized versions of common patterns found in
335programs. Many of them are merely methods to get around deficiencies
336in the language, and can be quite messy to implement in some
337languages.</p>
338
339
340
341<h2><a name="sec9" id="sec9"></a>
342Metasoftware</h2>
343
344<p class="first">Some types of programs could be written easily if the language were
345customizable, but are nearly impossible to write when it is not.</p>
346
347<h3><a name="sec10" id="sec10"></a>
348Runtime Generated Classes</h3>
349
350<p class="first">Say you wanted to write a video game where players could create their
351own objects, attach behaviors to the objects, and perhaps mix
352different objects together to create new ones. When you abstract the
353problem this looks just like an object system! Wouldn't it be nice if
354your program could create new objects and methods on the fly portably?</p>
355
356
357<h3><a name="sec11" id="sec11"></a>
358Object Inspection</h3>
359
360<p class="first">Imagine if you were developing a complicated program with many
361different objects that interacted in fairly complex ways. A tool to
362inspect the structure of objects while debugging would be quite
363useful, but in a traditional language would be impossible to implement
364portably. This could force you to purchase a certain compiler
365implementation which provided one, and even then would more than
366likely not be customizable.</p>
367
368<p>This problem can be generalized to apply to most debugging tools; it
369would be useful to write such tools portably because users of the
370<em>language</em> and not the <em>compiler</em> need to debug software. Sharing
371infrastructure would result in better tools (more developers), and
372save man-years of wasted effort that comes with having to rewrite
373non-portable functionality from scratch multiple times.</p>
374
375
376
377<h2><a name="sec12" id="sec12"></a>
378Metaobject Protocols</h2>
379
380<h3><a name="sec13" id="sec13"></a>
381Limited/Generalized Internals of the Implementation</h3>
382
383<p class="first">A Metaobject protocol is a generalized and limited subset of the
384underlying implementation of the language. It is generalized and
385limited in scope to allow for multiple implementation strategies;
386this, along with careful design, is essential because programming
387language research is ever advancing and new techniques for creating
388more reliable and faster implementations are still being discovered.</p>
389
390<p>This subset of the implementation is exported as a set of methods on
391metaobjects. Thus the system is implemented in itself. The system can
392then be customized using the extension and overriding features of the
393system.</p>
394
395
396<h3><a name="sec14" id="sec14"></a>
397Classes of MOPs</h3>
398
399<h4><a name="sec15" id="sec15"></a>
400Reflective</h4>
401
402<p class="first">A reflective MOP provides a functional/procedural interface to
403information about the system. It exposes class relationships, the
404methods are attached to a generic, etc. A reflective MOP often
405provides some functionality for creating new classes at runtime.</p>
406
407<h5>Example: Object Inspector</h5>
408
409
410<h5>Example: Runtime Generated Classes and Methods</h5>
411
412
413
414<h4><a name="sec16" id="sec16"></a>
415Intercessory</h4>
416
417<p class="first">Intercessory MOPs allow the user to customize language behavior by
418implementing methods which override certain aspects of the language
419behavior. This class of MOPs are what make MOPs especially
420powerful. No longer must a problem be restructured to fit the
421implementation language; the underyling language can be reshaped to
422fit the task at hand, and obfuscation of the intended structure of the
423application can be avoided.</p>
424
425<h5>Example: Lazily Allocated Slots</h5>
426
427
428<h5>Example: Observer Design Pattern</h5>
429
430
431
432
433<h3><a name="sec17" id="sec17"></a>
434Violation of Encapsulation?</h3>
435
436<p class="first">A MOP may seem like a violation of encapsulation by revealing some
437implementation details, but in reality a well designed protocol does
438not reveal anything which was not already exposed. Implementation
439decisions affect users, and some of these details do leak through to
440higher levels (e.g. the memory layout of slots). Implicit in the
441protocol specification are these implementation details, and the MOP
442merely makes this limited subset available for customization.</p>
443
444<p>A MOP makes it possible to customize certain implementation decisions
445that do not <strong>radically</strong> alter the behavior of the base language. The
446conceptual vocabulary of the system retains its meaning, and so code
447written in one dialect can interact with code written in another
448without knowing that they speak different ones.</p>
449
450
451
452<h2><a name="sec18" id="sec18"></a>
453MOP Design Principles</h2>
454
455<h3><a name="sec19" id="sec19"></a>
456Layered Protocol</h3>
457
458<p class="first">A layered protocol design is good for both meta and normal object
459protocols, and enables a combinatorial explosion of customizations to
460the protocol.</p>
461
462<h4><a name="sec20" id="sec20"></a>
463Top level <strong>must</strong> call lower level functions</h4>
464
465<p class="first">The top level methods of a layered metaobject protocol are required to
466call certain methods to perform some tasks. This both makes it easier
467to customize the top level methods (which perform very broad tasks) by
468providing some pieces of them for the programmer, and allows more
469customization to be done by opening up the replacement of lower level
470functions as a way to alter a small detail of the high level behavior.</p>
471
472
473<h4><a name="sec21" id="sec21"></a>
474Lower level methods are easier to customize</h4>
475
476<p class="first">The lower level methods of a MOP are limited in scope and can be
477implemented easily. Often the changes to language behavior that are
478wanted are very small, and having methods that perform simple tasks
479which are often customized reduces the effort required to extend the
480system.</p>
481
482
483
484<h3><a name="sec22" id="sec22"></a>
485Functional Where Possible</h3>
486
487<p class="first">Functional protocols are preferred for MOPs (and object protocol in
488general). Functional protocols open up several optimizations for the
489implementation without burdening the user of the protocol.</p>
490
491<h4><a name="sec23" id="sec23"></a>
492Memoization</h4>
493
494<p class="first">Memoization is the process of saving the results of a function call
495for future use. This avoids expensive recomputation of values which
496have not changed (recall that a true function will always return the
497same result when given the same arguments).</p>
498
499<p>A functional MOP can be optimized easily by exploiting this property
500to memoize the return values of calls to expensive operations. A MOP
501must be be very fast to avoid making programs unusably slow, and
502memoization is able to give an appreciable speedup in many cases
503without an insignificant burden on memory usage.</p>
504
505<h5>Constant Shared Return Values</h5>
506
507<p>Disallowing the modification of values returned by protocol methods
508allows the implementation to return large data structures by reference
509to avoid expensive copying without having to do expensive data
510integrity checks.</p>
511
512
513
514<h4><a name="sec24" id="sec24"></a>
515Cleaner Code</h4>
516
517
518
519<h3><a name="sec25" id="sec25"></a>
520Procedural Only Where Neccesary</h3>
521
522<p class="first">Some operations like method invocation are inheretly stateful and so
523must use a procedural protocol. There is no benefit to be gained from
524using a functional protocol, and indeed an attempt would result in
525obtuse code that severely restricted the implementor. Do note that
526only a very small part of method invocation is stateful (the actual
527call), and most of it can be implemented functionally (e.g. computing
528the discriminating function).</p>
529
530
531
532<h2><a name="sec26" id="sec26"></a>
533Examples</h2>
534
535<h3><a name="sec27" id="sec27"></a>
536Object Inspector</h3>
537
538<p class="first">A primitive portable object inspector is presented here.</p>
539
540<pre class="src">
541(<span style="color: #00ffff;">defgeneric</span> <span style="color: #87cefa;">example-inspect</span> (instance)
542 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Simple object inspector using CLOS MOP"</span>))
543
544(<span style="color: #00ffff;">defmethod</span> <span style="color: #87cefa;">example-inspect</span> ((instance t))
545 (format t <span style="color: #b3b3b3;">"Simple Object~% Value: ~S~%"</span> instance))
546
547(<span style="color: #00ffff;">defmethod</span> <span style="color: #87cefa;">example-inspect</span> ((instance standard-object))
548 (<span style="color: #00ffff;">let</span> ((class (class-of instance)))
549 (format t <span style="color: #b3b3b3;">"Class: ~S, Superclasses: ~S~%"</span>
550 (class-name class)
551 (mapcar #'class-name
552 (class-precedence-list class)))
553 (<span style="color: #00ffff;">let</span> ((slot-names (mapcar #'slot-definition-name
554 (class-slots class))))
555 (format t <span style="color: #b3b3b3;">"Slots: ~%~{ ~S~%~}"</span> slot-names)
556 (inspect-loop slot-names instance #'example-inspect))))
557
558(<span style="color: #00ffff;">defun</span> <span style="color: #87cefa;">inspect-loop</span> (slots instance inspector)
559 (format t <span style="color: #b3b3b3;">"Enter slot to inspect or :pop to go up one level: "</span>)
560 (finish-output)
561 (<span style="color: #00ffff;">let*</span> ((slot (read))
562 (found-slot (member slot slots)))
563 (<span style="color: #00ffff;">cond</span> (found-slot
564 (funcall inspector (slot-value instance slot))
565 (funcall inspector instance))
566 ((eq slot <span style="color: #b0c4de;">:pop</span>) t)
567 (t
568 (format t <span style="color: #b3b3b3;">"~S is invalid. Valid slot names: ~S~%"</span>
569 slot
570 slots)
571 (inspect-loop slots instance inspector)))))
572</pre>
573
574
575<h3><a name="sec28" id="sec28"></a>
576Observer Design Pattern</h3>
577
578<p class="first">A simple implementation of the observer pattern is under 100 lines,
579and the user level code requires only a single line of code to make
580any existing class observable.</p>
581
582<p>In a language lacking a MOP, implementing the observer pattern
583requires modifying every accessor of a class to explicitly invoke any
584observers, and neccesitates the addition of a mixin class to the class
585heirarchy. The fact that an object can be observed is a meta property
586of the class, and forcing it to be implemented at the application
587level dirties the inheritance heirarchy and adds uneccesary meta
588details to the program.</p>
589
590<pre class="src">
591<span style="color: #ff7f24;">;;; </span><span style="color: #ff7f24;">This metaclass adds a slot to instances which use it, and so the
592</span><span style="color: #ff7f24;">;;; </span><span style="color: #ff7f24;">system is defined in its own package to avoid name conflicts
593</span>(<span style="color: #00ffff;">defpackage</span> <span style="color: #98fb98;">:observer</span>
594 (<span style="color: #b0c4de;">:use</span> <span style="color: #b0c4de;">:cl</span> #+sbcl <span style="color: #b0c4de;">:sb-mop</span>)
595 (<span style="color: #b0c4de;">:export</span> observable register-observer unregister-observer))
596
597(<span style="color: #00ffff;">in-package</span> <span style="color: #b0c4de;">:observer</span>)
598
599<span style="color: #ff7f24;">;;; </span><span style="color: #ff7f24;">Metaclass
600</span>(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">observable</span> (standard-class)
601 ()
602 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Metaclass for observable objects"</span>))
603
604(<span style="color: #00ffff;">defmethod</span> <span style="color: #87cefa;">compute-slots</span> ((class observable))
605 <span style="color: #b3b3b3;">"Add a slot for storing observers to observable instances"</span>
606 (cons (make-instance 'standard-effective-slot-definition
607 <span style="color: #b0c4de;">:name</span> 'observers
608 <span style="color: #b0c4de;">:initform</span> '(make-hash-table)
609 <span style="color: #b0c4de;">:initfunction</span> #'(<span style="color: #00ffff;">lambda</span> () (make-hash-table)))
610 (call-next-method)))
611
612(<span style="color: #00ffff;">defmethod</span> <span style="color: #87cefa;">validate-superclass</span> ((class observable)
613 (super standard-class))
614 t)
615
616(<span style="color: #00ffff;">defun</span> <span style="color: #87cefa;">register-observer</span> (instance slot-name key closure)
617 (register-observer-with-class (class-of instance)
618 instance
619 slot-name
620 key
621 closure))
622
623(<span style="color: #00ffff;">defun</span> <span style="color: #87cefa;">unregister-observer</span> (instance slot-name key)
624 (unregister-observer-with-class (class-of instance)
625 instance
626 slot-name
627 key))
628
629(<span style="color: #00ffff;">defun</span> <span style="color: #87cefa;">get-observers</span> (instance slot-name)
630 (get-observers-with-class (class-of instance)
631 instance
632 slot-name))
633
634(<span style="color: #00ffff;">defun</span> <span style="color: #87cefa;">add-observer-table</span> (instance slot-name)
635 (setf (gethash slot-name (slot-value instance
636 'observers))
637 (make-hash-table)))
638
639(<span style="color: #00ffff;">defgeneric</span> <span style="color: #87cefa;">register-observer-with-class</span> (class instance slot-name key closure))
640(<span style="color: #00ffff;">defgeneric</span> <span style="color: #87cefa;">unregister-observer-with-class</span> (class
641 instance
642 slot-name
643 key))
644
645(<span style="color: #00ffff;">defmethod</span> <span style="color: #87cefa;">register-observer-with-class</span> ((class observable)
646 instance
647 slot-name
648 key
649 closure)
650 (setf (gethash key
651 (or (gethash slot-name
652 (slot-value instance 'observers))
653 <span style="color: #ff7f24;">;; </span><span style="color: #ff7f24;">Lazily add observer hash tables
654</span> (add-observer-table instance slot-name)))
655 closure))
656
657(<span style="color: #00ffff;">defmethod</span> <span style="color: #87cefa;">unregister-observer-with-class</span> ((class observable)
658 instance
659 slot-name
660 key)
661 (remhash key (gethash slot-name
662 (slot-value instance 'observers))))
663
664(<span style="color: #00ffff;">defmethod</span> <span style="color: #87cefa;">get-observers-with-class</span> ((class observable)
665 instance
666 slot-name)
667 (gethash slot-name (slot-value instance 'observers)))
668
669(<span style="color: #00ffff;">defmethod</span> (<span style="color: #87cefa;">setf slot-value-using-class)</span> <span style="color: #b0c4de;">:before</span> (new-value
670 (class observable)
671 instance
672 slot)
673 (<span style="color: #00ffff;">let</span> ((slot-name (slot-definition-name slot)))
674 (<span style="color: #00ffff;">if</span> (not (eq 'observers slot-name))
675 (<span style="color: #00ffff;">let</span> ((observers
676 (get-observers instance (slot-definition-name slot))))
677 (<span style="color: #00ffff;">if</span> observers
678 (maphash #'(<span style="color: #00ffff;">lambda</span> (key observer)
679 (funcall observer
680 (<span style="color: #00ffff;">if</span> (slot-boundp instance slot-name)
681 (slot-value instance slot-name)
682 nil)
683 new-value))
684 observers))))))
685</pre>
686
687
688<h3><a name="sec29" id="sec29"></a>
689Real World</h3>
690
691<h4><a name="sec30" id="sec30"></a>
692<a href="http://common-lisp.net/project/ucw/">UCW</a> and <a href="http://common-lisp.net/project/bese/arnesi.html">Arnesi</a></h4>
693
694<p class="first">Arnesi uses the CLOS MOP to implement methods which are transparantly
695rewritten into continuation passing style. This allows their execution
696to be suspended at certain points and resumed later. UCW builds on top
697of this to support a web framework where the statelessness of http is
698hidden from the user; displaying a page suspends the execution of the
699current continuation, and resumes it upon submission. The user level
700code is completely unaware of this.</p>
701
702
703<h4><a name="sec31" id="sec31"></a>
704<a href="http://clsql.b9.com">CLSQL</a></h4>
705
706<p class="first">CLSQL uses the reflective part of the CLOS MOP to map Common Lisp data
707types into SQL types, and the intercessory protocol for slot
708allocation to map slots onto database columns or sql expressions (for
709implementing relational slots).</p>
710
711
712<h4><a name="sec32" id="sec32"></a>
713<a href="http://common-lisp.net/project/elephant/">Elephant</a></h4>
714
715<p class="first">Elephant uses the CLOS MOP to transparantly store any class to disk
716and handle paging between the disk store and memory efficiently and
717with no user intervention.</p>
718
719
720
721
722<h2><a name="sec33" id="sec33"></a>
723Sources &amp;amp; Further Reading</h2>
724
725<h3><a name="sec34" id="sec34"></a>
726Sources</h3>
727
728<h4><a name="sec35" id="sec35"></a>
729The Art of the Metaobject Protocol</h4>
730
731<h5>Kiczales, Gregor et al. MIT Press 1991</h5>
732
733<p>Highly recommended reading even if you plan to never implement a MOP
734or use the CLOS one. The design principles it recommends are quite
735useful.</p>
736
737
738
739<h4><a name="sec36" id="sec36"></a>
740<a href="http://www.lisp.org/mop/contents.html">CLOS MOP Specification</a></h4>
741
742<p class="first">Specification of the MOP for CLOS defined in <em>The Art of the Metaobject Protocol</em>.</p>
743
744
745<h4><a name="sec37" id="sec37"></a>
746<a href="http://citeseer.ist.psu.edu/399658.html">Metaobject Protocols: Why We Want Them and What Else They Can Do</a></h4>
747
748<p class="first">A short overview of MOP design principles followed by three example
749metaobject protocols for Scheme.</p>
750
751
752<h4><a name="sec38" id="sec38"></a>
753<a href="http://www2.parc.com/csl/groups/sda/projects/oi/towards-talk/transcript.html">Why Are Black Boxes so Hard to Reuse?</a></h4>
754
755<p class="first">Transcription of a talk on the benefits of open implementations of
756software. It first discusses several problems that black box software
757implementations pose, and then presents existing solutions. It shows
758how the existing solutions are insufficient, and then provides
759metaobject protocols as a solution to most of the problems.</p>
760
761
762
763<h3><a name="sec39" id="sec39"></a>
764Further Reading</h3>
765
766<h4><a name="sec40" id="sec40"></a>
767<a href="http://citeseer.ist.psu.edu/chiba95metaobject.html">A Metaobject Protocol for C++</a></h4>
768
769<p class="first">Example of a purely compile time MOP. It implements the functionality
770of a code walker and something similar to the Lisp macro system.</p>
771
772
773<h4><a name="sec41" id="sec41"></a>
774<a href="http://www.parc.com/csl/groups/sda/publications/papers/Kiczales-TUT95/for-web.pdf">Open Implementations and Metaobject Protocols</a></h4>
775
776<p class="first">It is a bit long, but it seems to follow a similar structure to AMOP
777in introducing MOPs and their usefulness. The pages are slides with
778notes, and so the 331 pages might not actually take that long to read.</p>
779
780
781
782
783 <!-- Page published by Emacs Muse ends here -->
784
785 <p class="cke-buttons">
786 <!-- validating badges, any browser, etc -->
787 <a href="http://validator.w3.org/check/referer"><img
788 src="http://www.w3.org/Icons/valid-xhtml10"
789 alt="Valid XHTML 1.0!" /></a>
790
791 <a href="http://www.anybrowser.org/campaign/"><img
792 src="img/buttons/w3c_ab.png" alt="[ Viewable With Any Browser
793 ]" /></a>
794
795 <a href="http://www.debian.org/"><img
796 src="img/buttons/debian.png" alt="[ Powered by Debian ]" /></a>
797
798 <a href="http://hcoop.net/">
799 <img src="img/buttons/hcoop.png"
800 alt="[ Hosted by HCoop]" />
801 </a>
802
803 <a href="http://www.fsf.org/register_form?referrer=114">
804 <img src="img/buttons/fsf_member.png"
805 alt="[ FSF Associate Member ]" />
806 </a>
807 </p>
808
cb44b69b 809<p class="cke-footer">Mike: I WAS NOT MICROWAVED.
2aff8b5c 810</p>
811<p class="cke-timestamp">Last Modified:
812 March 13, 2008</p>
813 </body>
814</html>